package com.sz.biz.common.approval;

import com.sz.common.base.dao.Dao;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.i18n.I18nMessages;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.DateUtils;
import com.sz.common.core.system.service.SysUserSupport;
import com.sz.common.core.system.service.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Package: com.sz.biz.common.approval <br>
 * Function: TODO: ADD FUNCTION <br>
 * Author: Charles. <br>
 * Date: 2017-04-18 10:40:00.
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ApprovalServiceImpl extends AbstractService implements ApprovalService {

    @Autowired
    Dao dao;

    @Autowired
    SysUserSupport userSupport;

    @Autowired
    I18nMessages i18nMessages;


    /**
     * @param entityType
     * @param entityId
     * @param from
     * @param to
     * @param opinion
     * @param approvedBy
     */
    @Override
    public void approval(String entityType, String entityId, IApprovalStatus from, IApprovalStatus to,
                         String opinion, int approvedBy) {
        if (!StringUtils.hasLength(entityId) || !StringUtils.hasLength(entityType)) {
            throw new IllegalArgumentException("entity cannot be empty");
        }
        if (from == null || to == null) {
            throw new IllegalArgumentException("status cannot be empty");
        }
        if (!from.isTransitive(to)) {
            String msg = String.format("cannot change status from %s to %s", from.getName(), to.getName());
            throw new IllegalArgumentException(msg);
        }

        Approval approval = new Approval();
        approval.setOwnerId(entityId);
        approval.setOwnerType(entityType);
        approval.setFromStatus(from.getValue());
        approval.setToStatus(to.getValue());
        approval.setApprovalResult(true);
        approval.setApprovalOpinion(opinion);
        approval.setApprovedBy(approvedBy);

        dao.save(this.getSqlName("insertSelective"), approval);
    }

    /**
     * @param entityId
     * @param entityType
     * @return
     */
    @Override
    public Approval getLastApproval(String entityType, String entityId) {
        Map<String, String> map = new HashMap<>();
        map.put("ownerId", entityId);
        map.put("ownerType", entityType);
        Approval approval = (Approval) this.dao.findForObject(this.getSqlName("getLastApproval"), map);
        return approval;
    }

    /**
     * @param entityId
     * @param entityType
     * @return
     */
    @Override
    public List<Approval> getApprovals(String entityType, String entityId) {
        Map<String, String> map = new HashMap<>();
        map.put("ownerId", entityId);
        map.put("ownerType", entityType);
        List<Approval> list = this.dao.findForList(this.getSqlName("selectApprovals"), map, Approval.class);
        return list;
    }

    /**
     * 账单查看已出帐，已付款，逾期未结状态流转
     * @param entityType
     * @param entityId
     * @param billingStatus
     * @return
     */
    @Override
    public List<Approval> getApprovalsForBill(String entityType, String entityId, List<String> billingStatus) {
        ParamData paramData = new ParamData();
        paramData.put("ownerId", entityId);
        paramData.put("ownerType", entityType);
        paramData.put("billingStatus", billingStatus);
        List<Approval> list = this.dao.findForList(this.getSqlName("getApprovalsForBill"), paramData, Approval.class);
        return list;
    }

    /**
     * @param entityType
     * @param entityIds
     * @return
     */
    @Override
    public List<Approval> getLastApprovals(String entityType, List<String> entityIds) {
        Map<String, Object> map = new HashMap<>();
        map.put("list", entityIds);
        map.put("ownerType", entityType);
        List<Approval> list = dao.findForList(this.getSqlName("getLastApprovals"), map, Approval.class);
        return list;
    }

    /**
     * @param approvals
     * @return
     */
    @Override
    public List<String> formatOpinions(List<Approval> approvals) {
        List<String> opinions = new ArrayList<>();
        if (approvals != null && approvals.size() > 0) {
            List<Integer> userIds = new ArrayList<>();
            approvals.forEach(approval -> userIds.add(approval.getApprovedBy()));
            Map<Integer, UserModel> userMap = userSupport.getUsersMapById(userIds);

            for (Approval approval : approvals) {
                String approvedBy = "unknown";
                UserModel um = userMap.get(approval.getApprovedBy());
                if (um != null) {
                    approvedBy = um.getFullName();
                }
                String date = DateUtils.formatSimpleDate(approval.getApprovalTime());
                String message = i18nMessages.getMessage("biz.approval.message", new String[]{
                        approvedBy,
                        approval.getApprovalOpinion(),
                        date});
                opinions.add(message);
            }
        }
        return opinions;
    }

    /**
     * @param approval
     * @return
     */
    @Override
    public String getActionName(IApprovalStatus template, Approval approval) {
        String action = "";
        if (template != null) {
            action = template.getActionName(i18nMessages,approval);
        }
        return action;
    }

    @Override
    public void addApproval(Approval approval) {
        dao.save(this.getSqlName("insertSelective"), approval);
    }

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.common.approval..ApprovalMapper";
    }
}
